package com.example.demo.service;

import java.util.List;
import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;

/**
 * 测试Service,实现断路器功能
 * 
 * @author binbin.a.zhang
 *
 */
@Service
public class HelloService {
	@Autowired
	RestTemplate restTemplate;

	/**
	 * HystrixCommand 同步执行 fallbackMethod 服务降级调用的方法 commandKey 命令名称
	 * groupKey组名称，主要用来实现统计,默认的线程池划分也是根据groupKey来划分的 threadPoolKey
	 * 线程池划分,指定了threadPoolKey 实现了针对于Groupkey下的threadPoolKey更细粒度的线程池划分。
	 * ignoreExceptions 异常忽略，当指定了异常类型后，服务调用时如果触发了该异常，不会调用fallbackMehod
	 * 
	 * @return
	 */
	@HystrixCommand(fallbackMethod = "helloFallBack", commandKey = "helloService", groupKey = "Hello", threadPoolKey = "helloServiceIdThread", ignoreExceptions = ClassCastException.class)
	public String helloService() {
		return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
	}

	/**
	 * HystrixCommand 异步执行 fallbackMethod 服务降级调用的方法 ignoreExceptions
	 * 忽略的异常，当run方法运行时抛出指定的ClassCastException异常，
	 * 此时不会触发fallbackMethod,HystrixCommand会将ClassCastException包装在HystrixBadRequestException中抛出
	 * 
	 * @return
	 */
	@HystrixCommand(fallbackMethod = "helloFallBack", ignoreExceptions = ClassCastException.class)
	public Future<String> helloServiceAsync() {
		return new AsyncResult<String>() {
			@Override
			public String invoke() {
				return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
			}
		};
	}

	@SuppressWarnings("unused")
	private String helloFallBack() {
		return "Error";
	}

}
